<?php
require_once("../Datos/Campo.php");
require_once("../Datos/Tabla.php");
require_once("../Datos/Funcion.php");
class Selector{

	//Atributos del selector
	var $Nombre;
	var $Conexion;
	var $tablaBase;
	var $arrRelacionadas;
	var $arrCamposVisibles;
	var $arrCamposJunta;
	var $txtConsulta;
	var $txtCondicion;
	var $txtGrupo;
	var $txtHaving;
	var $txtOrden;
	var $esDistinct;
	var $limitar;
	var $inicioLimit;
	var $cantLimit;
	var $totalLimit;
		
	
	//---------------------------------------------------------------
	//Funciones del Selector---------------------------------------->
	
	function Selector(&$conexion){
		$this->Conexion = &$conexion;
		$this->txtConsulta = "";
		$this->txtCondicion="";
		$this->txtGrupo="";
		$this->txtHaving="";
		$this->txtOrden="";
		$this->esDistinct=0;
		$this->limitar = 0;
		$this->inicioLimit = 0;
		$this->cantLimit = 10;
		$this->totalLimit = 0;
	}
	
	function estTablaBase(&$base){
		$this->tablaBase = &$base;
		$this->tablaBase->estEsBase(1);
	}
	
	function agregarTablaRelacionada($tabla, $junta){
		
		$this->arrRelacionadas[$tabla->obttxtAlias()]['tabla'] = &$tabla;
		$this->arrRelacionadas[$tabla->obttxtAlias()]['junta'] = $junta;
	}
	
	function obtTablaRelacionada($nombreTabla){
		return $this->arrRelacionadas[$nombreTabla]['tabla'];
	}
	
	function obtTabla($nombreTabla){
		if($nombreTabla == $this->tablaBase->obttxtNombreTabla()){
			return $this->tablaBase;
		}
		else{
			return $this->arrRelacionadas[$nombreTabla]['tabla'];
		}
	}
	
	function &obtCampoRelacionado($nombreTabla, $nombreCampo){
		return $this->arrRelacionadas[$nombreTabla]['tabla']->obtCampo($nombreCampo);
	}
	
	function agregarCampoVisible($campo){
		if(strlen(@$campo->obtAlias()) > 0){
			$nombre = $campo->obtAlias();
		}
		else{
			$nombre = $campo->obtNombre();
		}

		$this->arrCamposVisibles[$nombre] = &$campo;
		if($campo->obtTabla() != $this->tablaBase){
			$campo->estNombreSelector($campo->obtNombreTabla());
		}
	}

	function obtVisibles(){
		return $this->arrCamposVisibles;
	}
	function obtVisiblesAlias(){
		$visiblesAlias = "";
		foreach($this->arrCamposVisibles as $visible){
			$alias = $visible->obtAlias();
			if($visible->obtAlias() == ""){$alias = $visible->obtNombre();}
			$visiblesAlias[$alias] = $visible;
		}
		return $visiblesAlias;
	}
	function &obtClavesBase(){
		$visibles = $this->arrCamposVisibles;
		if(!$this->obtEsAgrupado()){
			$claves = $this->tablaBase->obtCamposClave();
			$visibles = $this->arrCamposVisibles;
			
			foreach($visibles as $visible){
				foreach($claves as $clave){
				
					if($clave != 0){
						$nombreClave = $clave->obtNombreTabla().".".$clave->obtNombre();
						$nombreVisible = $visible->obtNombreTabla().".".$visible->obtNombre();
						if($nombreClave == $nombreVisible){
							if($visible->obtAlias() != '' && $visible->obtAlias() != $clave->obtNombre()){
								$vuelve[$visible->obtAlias()] = $visible;
								$claves[$clave->obtNombre()] = 0;
							}
						}	
					}
				}
				foreach($claves as $clave){
					if($clave != 0){
						$vuelve[$clave->obtNombre()] = $clave;
					}
				}
			}
		}
		else{
			foreach($visibles as $visible){
				if($visible->obtEsGrupo() == 1){
					if($visible->obtEsBase() == 1){
						$vuelve[$visible->obtAlias()] = $visible;
					}
					else{
						foreach($this->arrCamposJunta as $junta){
							if($junta['junta']->obtAliasTabla() == $visible->obtAliasTabla()){
								$vuelve[$junta['base']->obtNombre()] = $junta['base'];
							}
						}
					}
				}
			}
		}
		//die();
		return $vuelve;
	}

	function agregarCampoJunta(&$colBase, &$colRelacionada, $operador){
		$TCBase = $colBase->obtTabla();
		$TCRelacionada = $colRelacionada->obtTabla();
		
		if($TCBase->obttxtAlias() == $this->tablaBase->obttxtAlias() && 
		$TCRelacionada->obttxtAlias() == $this->arrRelacionadas[$colRelacionada->obtAliasTabla()]['tabla']->obttxtAlias()){
			
			$i = count($this->arrCamposJunta);
			$this->arrCamposJunta[$i]['base'] = &$colBase;
			$this->arrCamposJunta[$i]['junta'] = &$colRelacionada;
			$this->arrCamposJunta[$i]['operador'] = $operador;
		
		}
		else{
			die("Error en el paso de referencias agregando relaci�n.");
		}		
	}
	
	function obtResultado($cons = ''){
		if($cons == ''){
			$consultas[0] = $this->txtConsulta;
			if($this->limitar == 1){
				$nombres = array_keys($this->arrCamposVisibles);

				if($this->arrCamposVisibles[$nombres[0]]->obtAlias() != ''){
					$nombreCampo = $this->arrCamposVisibles[$nombres[0]]->obtAlias();
				}else{
					$nombreCampo = $this->arrCamposVisibles[$nombres[0]]->obtNombre();
				}
				
				$consultas[1] = "SELECT COUNT(".$nombreCampo.") as cant FROM(".substr($this->txtConsulta, 0, strrpos($this->txtConsulta, 'LIMIT')).") AS tblLimit";
			}
		}
		else{
			$consultas[0] = $cons;
		}
		$rdo = $this->Conexion->Ejecutar($consultas);
		$i=0;
		while($row_rdo = mysql_fetch_assoc($rdo[0])){
			$arr_rdo[$i] = $row_rdo;
			$i++;
		}
		if($this->limitar == 1){
			if(isset($rdo[1])){
				if($row_cant = mysql_fetch_assoc($rdo[1])){
					$this->totalLimit = $row_cant['cant'];
				}else{
					$this->totalLimit = 0;
				}
			}else{
				$this->totalLimit = 0;
			}
		}
		return @$arr_rdo;
	}
	
	function Ejecutar($post){
			$i=0;
			$nomVisibles = array_keys($this->arrCamposVisibles);
			
			foreach($nomVisibles as $nomCampo){
				$campo = &$this->arrCamposVisibles[$nomCampo];
				if($campo->obtEsBase() == 1){
					if($campo->obtEsReadOnly() == 0 && $campo->obtNoIngresar() == 0){
						//var_dump($campo->obtAlias());
						//var_dump($post[$i]);
						if(isset($post[$i])){
							$campo->estValor($post[$i]);
						}
					}
				}
				else{	
					if(isset($_SESSION[$campo->obtNombre()])){
					foreach(@$_SESSION[$campo->obtNombre()][$post[$i]] as $NombreJunta => $ValorJunta){
						//var_dump($NombreJunta);
						//var_dump($ValorJunta);
						foreach($this->arrCamposJunta as $fila){ 
							if($fila['junta']->obtNombre() == $NombreJunta && 
							   $fila['junta']->obtAliasTabla() == $campo->obtAliasTabla())
							   {
									$fila['base']->estValor($ValorJunta);
							   }
						}
					}
					}
				}
				$i++;
			}
			if(isset($_SESSION[$this->Nombre]) && $this->obtEsAgrupado() == false){
				foreach($_SESSION[$this->Nombre] as $Clave){
					$arrNombresClaves = array_keys($Clave);
					if(isset($this->tablaBase->arrPropiedades[$arrNombresClaves[0]])){
						$this->tablaBase->estPropiedad($arrNombresClaves[0], $Clave[$arrNombresClaves[0]]);
					}
					else{
						$nomVisibles = array_keys($this->arrCamposVisibles);
						foreach($nomVisibles as $nomCampo){
							$visible = &$this->arrCamposVisibles[$nomCampo];
							if($visible->obtAlias() == $arrNombresClaves[0]){
								$visible->estValor($Clave[$arrNombresClaves[0]]);
							}
						}
					}
				}
			}
			if($post['op'] == 'agregar'){return $this->tablaBase->Insertar();}
			if($post['op'] == 'borrar'){$this->tablaBase->Borrar();}
			if($post['op'] == 'modificar'){$this->tablaBase->Modificar();}
			
	}
	
	function estCondicion($condicion){
		$this->txtCondicion = $condicion;
		$this->txtConsulta = $this->GenerarConsulta();
	}
	function estHaving($having){
		$this->txtHaving = $having;
		$this->txtConsulta = $this->GenerarConsulta();
	}
	function AgregarCondicion($idCampo, $valor){
		if(strlen($valor) > 0){
			if(strlen($this->txtCondicion) > 0){
				$andWHERE = " AND ";	
			}else{
				$andWHERE = "";
			}
			
			if(strlen($this->txtHaving) > 0){
				$andHAVING = " AND ";	
			}else{
				$andHAVING = "";
			}
			
			$i=0;
			foreach($this->arrCamposVisibles as $visible){
				$signo = "%";
				if($i==$idCampo){
					if($visible->obtEsFuncion() == 0){
						if($visible->obtTipo() == "VARCHAR"){
							$cond = sprintf("%s LIKE '%s%s%s'", $visible->obtNombreTabla().".".$visible->obtNombre(), $signo, $valor, $signo);
						}
						else{
							$cond = sprintf("%s = '%s'", $visible->obtNombreTabla().".".$visible->obtNombre(), $valor);
						}
						$this->txtCondicion .= $andWHERE . $cond;
					}
					else{
						if($visible->obtTipo() == "VARCHAR"){
							$cond = sprintf("%s LIKE '%s%s%s'", $visible->obtAlias(), $signo, $valor, $signo);
						}
						else{
							$cond = sprintf("%s = '%s'", $visible->obtAlias(), $valor);
						}
						$this->txtHaving .= $andHAVING . $cond;
					}	
					$this->txtConsulta = $this->GenerarConsulta();
					//var_dump($this->txtConsulta);
				}
				$i++;
			}
		
			
		}
	}
	function estCondicionUno($columnas){
		$cond = $this->txtCondicion;
		$and = "";
		if(strlen($this->txtCondicion) > 0){
			$and = " AND ";
		}
		if(is_array($columnas)){
			$nombresColumnas = array_keys($columnas);
		}
		if(isset($nombresColumnas)){
		foreach($nombresColumnas as $nombre){	
			if(isset($this->arrCamposVisibles[$nombre])){
				$cond .= $and . $this->arrCamposVisibles[$nombre]->obtAliasTabla().".".$this->arrCamposVisibles[$nombre]->obtNombre()
				." = '" . $columnas[$nombre] . "'";
				$and = " AND ";
			}
			else{		
				foreach($this->obtClavesBase() as $clave){
					if(isset($columnas[$clave->obtAlias()])){
						$cond .= $and. $clave->obtNombreTabla().".".$clave->obtNombre() . " = '" . $columnas[$clave->obtAlias()] . "'"; 
						$and = " AND ";
					}
				}
			}
			
		}
		}
		$this->estCondicion($cond);
	}
	
	function GenerarConsulta($noAgrupar=0){	
			$this->estGrupo();
			$this->estOrden();
			$consulta = "SELECT";
			$coma = " ";
			
			if($this->esDistinct != 0){
				$consulta .= " DISTINCT";
			}
			
			foreach($this->arrCamposVisibles as $campo){
				$consulta .= $coma . $campo->obtExpresion();
				$coma = ", ";		
			}
			
			if($noAgrupar == 0){
			if($this->obtEsAgrupado() == false){
				if(is_array($this->tablaBase->obtNombresClaves())){
					$claves = array_keys($this->tablaBase->obtNombresClaves());
				}
				if(isset($claves)){
					foreach($claves as $clave){
						if(!isset($this->arrCamposVisibles[$clave])){
							$consulta .= $coma . $this->tablaBase->obttxtAlias().".".$clave;
							$coma = ", ";	
						}
					}
				}
			}
			else{
				foreach($this->arrCamposVisibles as $visible){
					if(count($this->arrCamposJunta) > 0){
						foreach($this->arrCamposJunta as $junta){	
							if($junta['junta']->obtNombreTabla() == $visible->obtNombreTabla() && 
							!isset($juntados[$junta['base']->obtAliasTabla().".".$junta['base']->obtNombre()]) &&
							!isset($this->arrCamposVisibles[$junta['base']->obtNombre()])){
								$consulta .= $coma . $junta['base']->obtAliasTabla().".".$junta['base']->obtNombre();
								$coma = ", ";
								$juntados[$junta['base']->obtAliasTabla().".".$junta['base']->obtNombre()] = "";
							}
						}
					}
				}
			}
			}
				
			$consulta .= " FROM " . $this->tablaBase->obttxtNombreTabla();
			if($this->tablaBase->obttxtNombreTabla() != $this->tablaBase->obttxtAlias()){
				$consulta .= " as " . $this->tablaBase->obttxtAlias();
			}
			
			if(count($this->arrRelacionadas) > 0){
				foreach($this->arrRelacionadas as $tabla){
					$consulta .= " " . $tabla['junta'] . " " . $tabla['tabla']->obttxtTabla();
					if($tabla['tabla']->obttxtTabla() != $tabla['tabla']->obttxtAlias()){
					 	$consulta .= " as " . $tabla['tabla']->obttxtAlias();
					}
					$and = " on ";
					foreach($this->arrCamposJunta as $campo){
						if($campo['junta']->obtAliasTabla() == $tabla['tabla']->obttxtAlias()){
							$consulta .= $and . $campo['base']->obtAliasTabla() .".".$campo['base']->obtNombre() . 
							" " . $campo['operador'] . 
							" " . $campo['junta']->obtAliasTabla().".".$campo['junta']->obtNombre();
							$and = " and ";
						}
					}
				}
			}
			
			if($this->txtCondicion != ""){
				$consulta .= " WHERE " . $this->txtCondicion;
			}
			if($this->txtGrupo != ""){
				$consulta .= " GROUP BY " . $this->txtGrupo;
			}
			if($this->txtHaving != ""){
				$consulta .= " HAVING " . $this->txtHaving;
			}
			if($this->txtOrden != ""){
				$consulta .= " ORDER BY " . $this->txtOrden;
			}
			if($this->limitar == 1){
				$consulta .= " LIMIT " . $this->inicioLimit .", ". $this->cantLimit;
			}
			//echo $consulta . "<br><br>";
			$this->txtConsulta = $consulta;
			return $consulta;
	}
	
	function obtOpciones(&$campo){
		$CTabla = &$campo->obtTabla();
		$claves = $CTabla->obtNombresClaves();
		//var_dump($campo->obtTabla());
		$columnas = array_keys($claves);
		$coma = " ";
		$consulta = "SELECT";
		foreach($columnas as $col){
			$consulta .= $coma . $CTabla->obttxtAlias().".".$col;
			$coma = ", ";
		}
		$consulta .= $coma . $campo->obtExpresion();
		$consulta .= " FROM " . $CTabla->obttxtTabla();
		if($CTabla->obttxtTabla() != $CTabla->obttxtAlias()){
			$consulta .= " as " . $CTabla->obttxtAlias();
		}
		$rdo = $this->obtResultado($consulta);
		return $rdo;
	}	
	
	function &obtClavesOpcion(&$campo){
		$CTabla = &$campo->obtTabla();
		return $CTabla->obtCamposClave();
	}
	
	function &obtConexion(){
		return $this->Conexion;
	}
	function obtNombre(){
		return $this->Nombre;
	}
	function obtConsulta(){
		return $this->txtConsulta;
	}
	function obtEsAgrupado(){
		if(strlen($this->txtGrupo) > 0){
			return true;
		}else{
			return false;
		}
	}
	function estGrupo(){
		$grupo = "";
		$coma = "";
		foreach($this->arrCamposVisibles as $visible){
			if($visible->obtEsGrupo() == 1){
				$arrCuentaEspacios = explode(" ", $visible->obtAlias());
				$comilla = "";
				if(count($arrCuentaEspacios) > 1){
					$comilla = "'";
				}
				$grupo .= $coma. $comilla .$visible->obtAlias(). $comilla;
				$coma = ", ";
			}
		}
		$this->txtGrupo = $grupo;
	}
	function estOrden(){
		$orden = "";
		$coma = "";
		foreach($this->arrCamposVisibles as $visible){
			if(strlen(@$visible->obtEsOrden()) > 1){
				$orden .= $coma. "'" . $visible->obtAlias() . "' ".$visible->obtEsOrden();
				$coma = ", ";
			}
		}
		$this->txtOrden = $orden;
	}
	
	function estEsDistinct($distinct){
		$this->esDistinct = $distinct;
	}
	
	function estLimitar($lim){
		$this->limitar = $lim;
		$this->GenerarConsulta();
	}
	function obtLimitar(){
		return $this->limitar;
	}
	
	function estInicioLimit($inicio){
		$this->inicioLimit = $inicio;
		$this->GenerarConsulta();
	}
	function obtInicioLimit(){
		return $this->inicioLimit;
	}
	
	function estCantLimit($cant){
		$this->cantLimit = $cant;
	}
	function obtCantLimit(){
		return $this->cantLimit;
	}
	function obtTotalLimit(){
		return $this->totalLimit;
	}
}
?>